package com.yanqu.road.server.manager.activity.channelmusicroomrank;


import com.yanqu.road.dao.impl.activity.channelmusicroomrank.CrossChannelMusicRoomRankRoundDaoImpl;
import com.yanqu.road.dao.impl.activity.channelmusicroomrank.CrossChannelMusicRoomRankShowDaoImpl;
import com.yanqu.road.entity.activity.channelmusicroomrank.ChannelMusicRoomRankDetailConfig;
import com.yanqu.road.entity.activity.channelmusicroomrank.CrossChannelMusicRoomRankRoundData;
import com.yanqu.road.entity.activity.channelmusicroomrank.CrossChannelMusicRoomRankShowData;
import com.yanqu.road.entity.player.UserBaseInfo;

import com.yanqu.road.logic.activity.channelmusicroomrank.ChannelMusicRoomRankConfig;
import com.yanqu.road.logic.pb.PlayerBasePb;

import com.yanqu.road.pb.activity.ChannelMusicRoomRankProto;
import com.yanqu.road.server.manager.user.CrossUserMgr;
import com.yanqu.road.server.protocol.GameErrorCode;
import com.yanqu.road.utils.RandomHelper;
import com.yanqu.road.utils.date.DateHelper;
import com.yanqu.road.utils.string.StringUtils;

import java.util.*;

public class ChannelMusicRoomRankShowRoom {
    private ChannelMusicRoomRankActivity activity;
    /**
     * 当前回合数据
     */
    private CrossChannelMusicRoomRankRoundData roundData;
    /**
     * 当前演出数据
     */
    private List<CrossChannelMusicRoomRankShowData> showDataList = new ArrayList<>();
    /**
     * 参赛的玩家美女 userId -> beautyId -> skinIds
     */
    private Map<Long, Map<Integer, Set<Integer>>> joinBeautyMap = new HashMap<>();

    public ChannelMusicRoomRankShowRoom(ChannelMusicRoomRankActivity activity, CrossChannelMusicRoomRankRoundData roundData, List<CrossChannelMusicRoomRankShowData> showDataList) {
        this.activity = activity;
        this.roundData = roundData;
        this.showDataList = showDataList;

        for (CrossChannelMusicRoomRankShowData showData : showDataList) {
            addUserBeautySkin(showData.getUserId(), showData.getBeautyId(), showData.getSkinId());
        }
    }

    public void addUserBeautySkin(long userId, int beautyId, int skinId) {
        Map<Integer, Set<Integer>> skinMap = joinBeautyMap.get(userId);
        if (skinMap == null) {
            skinMap = new HashMap<>();
            joinBeautyMap.put(userId, skinMap);
        }
        Set<Integer> skinIds = skinMap.get(beautyId);
        if (skinIds == null) {
            skinIds = new HashSet<>();
            skinMap.put(beautyId, skinIds);
        }
        skinIds.add(skinId);
    }

    public int getRemainNum() {
        ChannelMusicRoomRankConfig config = activity.getConfig();
        if (config == null) {
            return 0;
        }
        if (config.getMaxShowBeautyNum() <= showDataList.size()) {
            return 0;
        }
        return config.getMaxShowBeautyNum() - showDataList.size();
    }

    public boolean isFull() {
        return getRemainNum() == 0;
    }

    public boolean isTimeEnd() {
        ChannelMusicRoomRankConfig config = activity.getConfig();
        long endTime = config.getRoundEndTime(roundData.getStartTime());
        int currentSecond = DateHelper.getCurrentSecond();
        if (currentSecond >= endTime) {
            return true;
        }
        return false;
    }

    public boolean isFinish() {
        return roundData.getFinishTime() != 0;
    }

    public int getTheme() {
        return roundData.getTheme();
    }

    public int getRound() {
        return roundData.getRound();
    }

    public long getStartTime() {
        return roundData.getStartTime();
    }

    public long getFinishTime() {
        return roundData.getFinishTime();
    }

    public ChannelMusicRoomRankProto.ChannelMusicRoomRankMainSceneRespMsg.Builder getMainSceneMsg() {
        ChannelMusicRoomRankProto.ChannelMusicRoomRankMainSceneRespMsg.Builder builder = ChannelMusicRoomRankProto.ChannelMusicRoomRankMainSceneRespMsg.newBuilder();
        builder.setRet(0);
        if (roundData == null) {
            return builder;
        }
        builder.setTheme(roundData.getTheme());
        builder.setStartTime(roundData.getStartTime());
        builder.setEndTime(CrossChannelMusicRoomRankConfigMgr.getConfig(roundData.getActivityId()).getRoundEndTime(roundData.getStartTime()));
        builder.setRound(roundData.getRound());
        builder.setRemainNum(getRemainNum());
        for (CrossChannelMusicRoomRankShowData showData : showDataList) {
            ChannelMusicRoomRankProto.ChannelMusicRoomRankShowTemp.Builder showTempBuilder = ChannelMusicRoomRankProto.ChannelMusicRoomRankShowTemp.newBuilder();
            showTempBuilder.setBeautyId(showData.getBeautyId());
            showTempBuilder.setSkinId(showData.getSkinId());
            showTempBuilder.setScore(activity.getConfig().calcThemeScore(showData, roundData.getTheme()));
            UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(showData.getUserId());
            showTempBuilder.setUserBaseInfo(PlayerBasePb.parsePlayerBaseTempMsg(userBaseInfo));
            showTempBuilder.setIndex(showData.getJoinPos());
            showTempBuilder.setUserId(showData.getUserId());
            builder.addShowData(showTempBuilder);
        }

        return builder;
    }

    /**
     * 时辰卡累计使用同步
     */
    public void syncCardUsed(long userId, int amount) {
        for (CrossChannelMusicRoomRankShowData showData : showDataList) {
            if (showData.getUserId() == userId && showData.getCardAmount() != amount) {
                showData.setCardAmount(amount);
            }
        }
    }

    /**
     * 结算
     */
    public synchronized ChannelMusicRoomRankHistoryShowRoom settle() {
        ChannelMusicRoomRankConfig config = activity.getConfig();
        int theme = roundData.getTheme();

        //先按积分排序
        for (CrossChannelMusicRoomRankShowData showData : showDataList) {
            config.calcAndSetShowScore(showData, theme);
        }
        showDataList.sort((o1, o2) -> {
            int compare = Long.compare(o2.getShowScore(), o1.getShowScore());
            if (compare == 0) {
                compare = Integer.compare(o1.getJoinPos(), o2.getJoinPos());
            }
            return compare;
        });

        //然后分配排名权重
        LinkedList<Map<Integer, Long>> weightMapList = new LinkedList<>();
        for (int i = 0; i < showDataList.size(); i++) {
            int scoreRank = i + 1;
            int listIndex = config.getScoreRankListIndex(scoreRank);
            CrossChannelMusicRoomRankShowData showData = showDataList.get(i);

            if (listIndex >= weightMapList.size()) {
                Map<Integer, Long> weightMap = new HashMap<>();
                weightMapList.addLast(weightMap);
            }
            Map<Integer, Long> weightMap = weightMapList.get(listIndex);
            weightMap.put(i, showData.getShowScore());
        }

        Set<Long> waitSettleServerIdSet = new HashSet<>();
        //按权重随机排名
        int size = showDataList.size();
        List<CrossChannelMusicRoomRankShowData> resultList = new ArrayList<>();
        for (int i = 0; i < size; i++) {
            int showRank = i + 1;
            Map<Integer, Long> weightMap = weightMapList.getFirst();
            int index = RandomHelper.getRandomKeyByLongWeight(weightMap);
            CrossChannelMusicRoomRankShowData showData = showDataList.get(index);

            showData.setRank(showRank);
            ChannelMusicRoomRankDetailConfig rankConfig = activity.getConfig().getRankConfigByRank(showRank);
            if (rankConfig != null) {
                long rankScore = rankConfig.getScore();
                //需求变更,时辰卡使用加成,在总值里计算,这里不计算
//                int cardUseAmountBuffValue = config.getCardUseAmountBuffValue(showData.getCardAmount());
//                long newRankScore = BigDecimal.valueOf(rankScore).multiply((BigDecimal.valueOf(cardUseAmountBuffValue + 1000).divide(BigDecimal.valueOf(1000)))).longValue();
//                long buffAddScore = newRankScore - rankScore;
//                showData.setRankScore(newRankScore);
//                showData.setBuffAddScore(buffAddScore);
                showData.setRankScore(rankScore);
                showData.setBuffAddScore(0);
            }
            resultList.add(showData);

            weightMap.remove(index);
            if (weightMap.isEmpty()) {
                weightMapList.removeFirst();
            }

            UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(showData.getUserId());
            if (userBaseInfo != null) {
                waitSettleServerIdSet.add(userBaseInfo.getServerId());
            }
        }

        roundData.setFinishTime(DateHelper.getCurrentSecond());
        roundData.setWaitSettleServerSet(waitSettleServerIdSet);
        ChannelMusicRoomRankHistoryShowRoom historyShowRoom = new ChannelMusicRoomRankHistoryShowRoom(roundData, resultList);
        return historyShowRoom;
    }

    /**
     * 参加演出
     *
     * @param userId
     * @param beautyId
     * @param skinId
     * @param attrList
     * @param cardUsedAmount
     * @return
     */
    public synchronized int joinShow(long userId, int beautyId, int skinId, List<Long> attrList, int cardUsedAmount, String cost) {
        if (isFull()) {
            return GameErrorCode.E_MUSIC_ROOM_RANK_ROOM_FULL;
        }
        if (isTimeEnd()) {
            return GameErrorCode.E_MUSIC_ROOM_RANK_ROUND_TIME_END;
        }
        if (isFinish()) {
            return GameErrorCode.E_MUSIC_ROOM_RANK_ROUND_END;
        }
        if (joinBeautyMap.containsKey(userId)) {
            Map<Integer, Set<Integer>> beautyMap = joinBeautyMap.get(userId);
            int upNum = 0;
            for (Set<Integer> tempSkinIds : beautyMap.values()) {
                upNum += tempSkinIds.size();
            }
            if (upNum >= activity.getConfig().getMaxUserBeautyNum()) {
                return GameErrorCode.E_MUSIC_ROOM_RANK_MAX_SHOW_BEAUTY_NUM;
            }
            if (beautyMap.get(beautyId) != null) {
                if (beautyMap.get(beautyId).contains(skinId)) {
                    return GameErrorCode.E_MUSIC_ROOM_RANK_REPEAT_JOIN;
                }
            }
        }

        int costType = 0;
        if (!StringUtils.isNullOrEmpty(cost)) {
            costType = 1;
        }

        CrossChannelMusicRoomRankShowData showData = new CrossChannelMusicRoomRankShowData(roundData.getActivityId(), roundData.getRound(), userId, beautyId, skinId, costType);
        showData.setAttrList(attrList);
        showData.setJoinPos(showDataList.size() + 1);
        showData.setJoinTime(DateHelper.getCurrentTime());
        showData.setCardAmount(cardUsedAmount);

        synchronized (showDataList) {
            showDataList.add(showData);
        }
        addUserBeautySkin(showData.getUserId(), showData.getBeautyId(), showData.getSkinId());
        return 0;
    }

    public void save() {
        if (roundData.isInsertOption()) {
            new CrossChannelMusicRoomRankRoundDaoImpl().add(roundData);
        } else if (roundData.isUpdateOption()) {
            new CrossChannelMusicRoomRankRoundDaoImpl().update(roundData);
        }
        List<CrossChannelMusicRoomRankShowData> saveList = new ArrayList<>();
        synchronized (showDataList) {
            saveList.addAll(showDataList);
        }

        for (CrossChannelMusicRoomRankShowData showData : saveList) {
            if (showData.isInsertOption()) {
                new CrossChannelMusicRoomRankShowDaoImpl().add(showData);
            } else if (showData.isUpdateOption()) {
                new CrossChannelMusicRoomRankShowDaoImpl().update(showData);
            }
        }
    }
}
